package day1;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.RedisSerializer;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;
import java.util.Set;

public class Redis3Demo {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    String PRE_LIKE ="liked";
    /**
     * 模拟一个点赞功能。
     * @param shopId：商品id
     * @param userId：用户id
     */
    public void like(String shopId,String userId){
        //判断当前用户是否点赞。
        if(stringRedisTemplate.opsForSet().isMember(PRE_LIKE+shopId,userId)){
            //已经点赞了：用户取消点赞：
            stringRedisTemplate.opsForSet().remove(PRE_LIKE+shopId,userId);
        }else{
            //用户点赞，就调用这个方法。无论用户点击多少次，都只算一次。
            stringRedisTemplate.opsForSet().add(PRE_LIKE+shopId,userId);
        }
        //统计点赞数量：
        stringRedisTemplate.opsForSet().size(PRE_LIKE+shopId);
    }




    /**
     * 模拟一个点赞功能。并且需要返回最先点赞的5个用户信息。这个需要Zset了。
     * @param shopId：商品id
     * @param userId：用户id
     */
    public void like2(String shopId,String userId){
        //判断当前用户是否点赞。只能通过 zscore 命令判断当前数据是否存在。
        if(stringRedisTemplate.opsForZSet().score(PRE_LIKE+shopId,userId) != null){
            //已经点赞了：用户取消点赞：
            stringRedisTemplate.opsForZSet().remove(PRE_LIKE+shopId,userId);
        }else{
            //用户点赞，就调用这个方法。无论用户点击多少次，都只算一次。
            stringRedisTemplate.opsForZSet().add(PRE_LIKE+shopId,userId,
                    System.currentTimeMillis());
        }

        //统计点赞数量：
        stringRedisTemplate.opsForSet().size(PRE_LIKE+shopId);
        //返回最先点赞的5个用户，在这里就是按照 score 升序排序。range(返回正数0-5)。reverseRange(返回倒数的0-5)；
        Set<String> users = stringRedisTemplate.opsForZSet().range(PRE_LIKE + shopId,
                0, 5);
    }


    /**
     * 使用bitmap设计一个是否签到的功能：
     * 每调用一次这个方法，就会将这个字段设置为1。
     */
    public void login(){
        //今天在一年中是第几天？
        int dayOfYear = LocalDate.now().getDayOfYear();
        //将这一天设置为 1
        stringRedisTemplate.opsForValue().setBit("login:key:2025",dayOfYear,true);
        //统计一下。由于当前的springboot中，没有这个指令的方法，所以我只能通过下面的方法，来获取。
        Long total = stringRedisTemplate.execute((RedisCallback<Long>) redisConnection -> redisConnection.bitCount("login:key:2025".getBytes()));
        System.out.println("今年一共登录了："+total+" 天！");
    }


    /**
     * HLL的使用，用来统计UV。
     */
    public void summary(String userId){
        //向key中添加一个元素。
        stringRedisTemplate.opsForHyperLogLog().add("user:view:page",userId);
        //统计有多少独立的用户。大概的。
        Long size = stringRedisTemplate.opsForHyperLogLog().size("user:view:page");
        System.out.println("大概有："+size+"人！");
    }

}
